<?php

/**
 * sfWidgetFormSchemaExt represents an array of fields.
 *
 * @package    symfony
 * @subpackage widget
 * @author     Jonathan Olger Nieto Lajo <jonathan_nieto@hotmail.com>
 */
class sfWidgetFormSchemaExt extends sfWidgetFormSchema
{
  public function render($name, $values = array(), $attributes = array(), $errors = array())
  {
    if (is_null($values))
    {
      $values = array();
    }

    if (!is_array($values) && !$values instanceof ArrayAccess)
    {
      throw new InvalidArgumentException('You must pass an array of values to render a widget schema');
    }

    $formFormat = $this->getFormFormatter();
    
    $rows = array();
    $hiddenRows = array();
    $errorRows = array();

    // render each field
    foreach ($this->positions as $name)
    {
      $widget = $this[$name];
      $value = isset($values[$name]) ? $values[$name] : null;
      $error = isset($errors[$name]) ? $errors[$name] : array();
      $widgetAttributes = isset($attributes[$name]) ? $attributes[$name] : array();

      if ($widget instanceof sfWidgetForm && $widget->isHidden())
      {
        $field = $this->renderField($name, $value, $widgetAttributes);
        
        $hiddenRows[] = $this->fixField($field);
      }
      else
      {
        //Deb::print_r_pre($value);echo '<br/>';
        $field = $this->renderField($name, $value, $widgetAttributes, $error);
        
        // don't add a label tag and errors if we embed a form schema
        $label = $widget instanceof sfWidgetFormSchema ? $this->getFormFormatter()->generateLabelName($name) : $this->getFormFormatter()->generateLabel($name);
        $error = $widget instanceof sfWidgetFormSchema ? array() : $error;
        
        //$rows[] = $formFormat->formatRowExt($label, $field, $error, $this->getHelp($name), null, $name);
        $field  = $formFormat->formatRowExt($label, $field, $error, $this->getHelp($name), null, $name);
        $rows[] = $this->fixField($field);
      }
    }

    if ($rows)
    {
      // insert hidden fields in the last row
      for ($i = 0, $max = count($rows); $i < $max; $i++)
      {
        $rows[$i] = strtr($rows[$i], array('%hidden_fields%' => $i == $max - 1 ? implode("\n", $hiddenRows) : ''));
      }
    }
    else
    {
      // only hidden fields
      $rows[0] = implode("\n", $hiddenRows);
    }
    
    
    $errorSchema = new sfValidatorErrorSchema(new sfValidatorSchema());
    if ($errors)
    {
      foreach ($errors as $key => $value)
      {
        if (preg_match('/(\[|\])+/', $value))// || ($value instanceof sfValidatorErrorSchema))
        {
          //$msg = sprintf('The %s form has some errors.', $key);
          //$errorSchema->addError(new sfValidatorErrorSchema(new sfValidatorPass(), array(new sfValidatorError(new sfValidatorPass(), $msg))), $key);
        }
        else
        {
          $errorSchema->addError($value, $key);
        }
      }
    }
    
    $errors = $errorSchema;
    
    /*
    foreach ($errors as $key => $value)
    {
      echo $key.' => '.$value.'<br/>';
    }
    */
    
    
    
    return $this->getFormFormatter()->formatErrorRow($errors).implode('', $rows);
  }
  
  public function fixField($field)
  {
    if (preg_match_all('/@@@(\w+)@@@/', $field, $matches, PREG_SET_ORDER))
    {
      foreach ($matches as $match)
      {
        $field = str_replace($match[0], $this->generateName($match[1]), $field);
      }
    }
    
    if (preg_match_all('/%%%(\w+)%%%/', $field, $matches, PREG_SET_ORDER))
    {
      foreach ($matches as $match)
      {
        $field = str_replace($match[0], $this->generateId($this->generateName($match[1])), $field);
      }
    }

    return $field;
  }
  
  /**
   * Generates a form name.
   * 
   * This method is needed when using embedded forms and wants to know the future
   * "name" attribute of a widget, to use for javascript for example.
   *
   * @param string $name The name to convert
   *
   * @return string The generated name
   */
  public function generateLazyName($name)
  {
    return '@@@'.$name.'@@@';
  }
  /**
   * Generates a form id.
   * 
   * This method is needed when using embedded forms and wants to know the future
   * "id" attribute of a widget, to use for javascript for example.
   *
   * @param string $name The name to convert
   *
   * @return string The generated id
   */
  public function generateLazyId($name)
  {
    return '%%%'.$name.'%%%';
  }
}
